package club.pchome.common.util.jwt;

import club.pchome.common.util.RedisUtil;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by junao.yuan on 16-8-11.
 */
public class JwtUtils {
    private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);

	private static final String signKey = "msnUTwGpCRch9dCA40qzP1Yag5pA";
	private static final String CLAIMS_KEY = "JWT_BODY";

	private static final Integer REDIS_TIME = 30*60;
	//令牌过期时间，单位：s
    private static final long EXPIRATION_TIME = 60 * 60 * 1000;

	@Autowired
	private static RedisUtil redisUtil;

	private static Key checkKey(){

		return new SecretKeySpec(signKey.getBytes(), SignatureAlgorithm.HS512.getJcaName());
	}


	/**
	 * 创建Token
	 * @param jwtToken
	 * @return
	 * @throws Exception
	 */
	public static String createToken(JwtToken jwtToken) throws Exception {
		jwtToken.setTimestamp(String.valueOf(DateUtil.addMinute(new Date(), 30).getTime()));
//		jwtToken.setExpire(System.currentTimeMillis() + EXPIRATION_TIME);
		Map<String,Object> cl = new HashMap<String, Object>();
		cl.put(CLAIMS_KEY, JSONObject.toJSONString(jwtToken));
		
		long expMillis = System.currentTimeMillis() + EXPIRATION_TIME;
		Date expDate = new Date(expMillis);
		
		return 	Jwts.builder()
				.setClaims(cl)
				.signWith(SignatureAlgorithm.HS512, checkKey())
				.setExpiration(expDate)
				.compact();
	}

	/**
	 *
	 * @param httpServletRequest
	 * @return
	 * @throws Exception
	 */
	public static JwtToken parseToken(HttpServletRequest httpServletRequest) throws Exception {
		if(httpServletRequest.getAttribute("jwtToken")!=null){
			return (JwtToken) httpServletRequest.getAttribute("jwtToken");
		}
		return null;
	}


	/**
	 * 解析TOken
	 * @param token
	 * @return
	 * @throws Exception
	 */
	public static JwtToken parseToken(String token) throws Exception {
		String json = (String) Jwts.parser().setSigningKey(checkKey()).parseClaimsJws(token).getBody().get(CLAIMS_KEY);
		return JSONObject.parseObject(json,JwtToken.class);
	}

	/**
	 * 刷新Token
	 * @throws Exception
	 */
	public static void refrechToken(String token) throws Exception {
		JwtToken jwtToken = parseToken(token);
		redisUtil.set(jwtToken.getTokenId(), token, REDIS_TIME);
	}


	/**
	 * 踢除TOken 并存入新Token
	 * @param jwtToken
	 * @throws Exception
	 */
	public static String awayToken(JwtToken jwtToken) throws Exception {
		String newToken = null;

		Object obj = redisUtil.get(jwtToken.getTokenId());
		if(obj != null){
			String token = redisUtil.get(jwtToken.getTokenId()).toString();
			if(false){
				JwtToken oldJwt = parseToken(token);
				if(oldJwt.getUserId().equals(jwtToken.getUserId())){
					redisUtil.del(oldJwt.getTokenId());
					newToken = createToken(jwtToken);
					logger.info("踢除上一次登录信息",oldJwt);
				}
				else{
					newToken = token;
				}

			}
			else{
				newToken = createToken(jwtToken);
			}
			redisUtil.set(jwtToken.getTokenId(), newToken, REDIS_TIME);
			logger.info("jwtTokenId:"+jwtToken.getTokenId());
			logger.info("jwtTokenVal:"+redisUtil.get(jwtToken.getTokenId()));
		}

		return newToken;
	}

	/**
	 * 获取jwt的payload部分
	 * @param token
	 * @return
	 */
	public static Claims getClaimFromToken(String token) {
		return Jwts.parser()
				.setSigningKey(checkKey())
				.parseClaimsJws(token)
				.getBody();
	}

	/**
	 * <pre>
	 *  验证token是否失效
	 *  true:过期 false:没过期
	 * </pre>
	 */
	public static Boolean isTokenExpired(String token) {
		final Date expiration = getExpirationDateFromToken(token);
		return expiration.before(new Date());
	}

	/**
	 * 获取token失效时间
	 * @param token
	 * @return
	 */
	public static Date getExpirationDateFromToken(String token) {
		try {
			//注意这里要是失效会报错
			return getClaimFromToken(token).getExpiration();
		}catch (Exception e){
			return new Date(0);
		}
	}

	public final static DateFormat YYYY_MM_DD_MM_HH_SS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	public static void main(String[] args) throws Exception {
		JwtToken jwtToken = new JwtToken();

		//        String token = createToken(jwtToken);
		//        System.out.println(token);
		//
		        jwtToken.setUserId(1l);
		        jwtToken.setDeviceId("android");
		        jwtToken.setAppVersion("1.0.0");
		        jwtToken.setAppKey("cloudbuy_pc");
		        jwtToken.setAppSecret("39822ed3feefa71c05373f24fa566826");
		//    	System.out.println(System.currentTimeMillis());
		//    	System.out.println(new Date().getTime());


		System.out.println(awayToken(jwtToken));
	}




}
